#ifndef _FileHandler_h_
#define _FileHandler_h_

/*
  Created to support linux file functions, such as identifying the logical drive name and UUID of the drive.
  These are stored with each media file in the database to track if it moves.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>	
#include <mntent.h> // These routines are used to access the file system description file /etc/fstab and the mounted file system description file /etc/mtab

// From package libblkid-dev, found it finally! link in blkid library
#include <blkid/blkid.h>

//============================================================================================================================
String GetDriveUUID(const char *devnm) {
	blkid_dev dev;
	blkid_cache cache;
	char *uuid;

	if (blkid_get_cache(&cache, NULL) == 0) { // Must be NULL or won't return crap
		if ((dev = blkid_get_dev(cache, devnm, BLKID_DEV_NORMAL)) != NULL) { // Call just to verify that dev exists before looking for tag; not necessary
			uuid = blkid_get_tag_value(cache, "UUID", devnm);
			return String(uuid);
		}
		blkid_put_cache(cache);  // Don't know if necessary
	}
	
	return String("Err");
}

//============================================================================================================================
struct mntent *mountpoint(const char *filename, struct mntent *mnt, char *buf, size_t buflen)
{
    struct stat s;
    FILE *      fp;
    dev_t       dev;

    if (stat(filename, &s) != 0) {
        return NULL;
    }

    dev = s.st_dev;

    if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
        return NULL;
    }

    while (getmntent_r(fp, mnt, buf, buflen)) {
        if (stat(mnt->mnt_dir, &s) != 0) {
            continue;
        }

        if (s.st_dev == dev) {
            endmntent(fp);
            return mnt;
        }
    }

    endmntent(fp);

    // Should never reach here.
    errno = EINVAL;
    return NULL;
}	

// Determine physical drive a file is on.  Important for storage considerations, determining space available. http://stackoverflow.com/questions/2337139/where-is-a-file-mounted
// Also useful to identify drive failure, recovery strategies, which backup to restore, separating duplicates between USB drives, CDs, and hard-drive space.
//============================================================================================================================
String GetDrive(String &path) {
	struct mntent mp;
	char buf[512];
	size_t buflen = sizeof buf;
	
	if (!mountpoint((const char *)path, &mp, (char *)buf, buflen))
		return String("Unknown");
	
/*
	struct mntent
	  {
	    char *mnt_fsname;           // Device or server for filesystem.  
	    char *mnt_dir;              // Directory mounted on.  
	    char *mnt_type;             // Type of filesystem: ufs, nfs, etc.  
	    char *mnt_opts;             // Comma-separated options for fs.  
	    int mnt_freq;               // Dump frequency (in days).  
	    int mnt_passno;             // Pass number for `fsck'.  
	  };
*/
	return String(mp.mnt_fsname);
	
/*		
	#include <sys/types.h>
	#include <sys/stat.h>
	#include <unistd.h>	
	
	stat()
	int stat(const char *path, struct stat *buf);
struct stat {
    dev_t     st_dev;     // ID of device containing file 
    __STD_TYPE __DEV_T_TYPE __dev_t dev_t
    #define __DEV_T_TYPE            __UQUAD_TYPE
    ino_t     st_ino;     // inode number 
    mode_t    st_mode;    // protection 
    nlink_t   st_nlink;   // number of hard links 
    uid_t     st_uid;     // user ID of owner 
    gid_t     st_gid;     // group ID of owner 
    dev_t     st_rdev;    // device ID (if special file) 
    off_t     st_size;    // total size, in bytes 
    blksize_t st_blksize; // blocksize for filesystem I/O 
    blkcnt_t  st_blocks;  // number of blocks allocated 
    time_t    st_atime;   // time of last access 
    time_t    st_mtime;   // time of last modification 
    time_t    st_ctime;   // time of last status change 
};
	
	The field st_atime is changed by file accesses, e.g. by execve(2), mknod(2), pipe(2), utime(2) and read(2) (of more than zero bytes). Other routines, like mmap(2), may or may not update st_atime.

	The field st_mtime is changed by file modifications, e.g. by mknod(2), truncate(2), utime(2) and write(2) (of more than zero bytes). Moreover, st_mtime of a directory is changed by the creation or deletion of files in that directory. The st_mtime field is not changed for changes in owner, group, hard link count, or mode.

	The field st_ctime is changed by writing or by setting inode information (i.e., owner, group, link count, mode, etc.).

	UUID is the only way to guarantee you recognize the same drive or partition no matter what. For example, if you introduce to your system another hard drive, this might upset quite a few things, starting with the way your system boots up (or stops booting up upon the new drive introduction). Using UUID helps remedy most of such things.

	UUIDs really useful for mounting my removable media  you can use UUID to always mount the same card at the same location.
	To list UUID on your system you can use command blkid
	mount -U 0ef96300-36c0-4575-8a1d-2d36ff4cd585 /mnt/disk1
	tune2fs -U uuid /dev/sda2
	
	blkid:
	/dev/sda1: LABEL="shows320" UUID="f510d49d-457b-47b7-a9b0-8030eb339461" TYPE="ext2" 
	/dev/sdb1: LABEL="downloads500" UUID="e9cb1d6f-0a64-4760-a7f6-0804ddc8ad6b" TYPE="ext4" 
	/dev/sdb5: UUID="29af4896-9fb2-4dfc-8b11-40f8eb73ca22" TYPE="swap" 
	/dev/sdc1: LABEL="spare320" UUID="39d8ebfb-749f-466d-9244-6763c42d77c1" TYPE="ext3" 
	/dev/sdd1: LABEL="green1000" UUID="331d760b-8492-4712-bd5a-ca9f88d9a56a" TYPE="ext2" 

int devid_deviceid_to_nmlist(char *search_path, ddi_devid_t devid,
	    char *minor_name, devid_nmlist_t **retlist);

A device ID consists of two parts: a major ID, identifying the class of the device, and a minor ID, identifying a specific instance of a device in that class. A device ID is represented using the type dev_t.
Given major and minor device IDs, makedev() combines these to produce a device ID, returned as the function result. This device ID can be given to mknod(2), for example.

The major() and minor() functions perform the converse task: given a device ID, they return, respectively, the major and minor components. These macros can be useful to, for example, decompose the device IDs in the structure returned by stat(2).  

CONFORMING TO

The makedev() major() and minor() functions are not specified in POSIX.1, but are present on many other systems.  
NOTES

These interfaces are defined as macros. Since glibc 2.3.3, they have been aliases for three GNU-specific functions: gnu_dev_makedev(3), gnu_dev_major(3), and gnu_dev_minor(3). The latter names are exported, but the traditional names are more portable.  

*/
}

String GetNetworkName() {
	// lspci -v|grep Ethernet -A 1
	// ifconfig inet addr:192.168.1.3 (Mac address?)
	// ethtool -i eth0
	// netstat -r => default         192.168.1.1
	// arp => ether   00:1b:2f:d6:ad:96
	// your ISP automatically assigns a single public address to your modem using PPP, bootp, or DHCP. This assigned address can change from time to time ("dynamic"). It requires no configuration on your part. Business customers typically obtain multiple public addresses from their ISP. These addresses do not change ("static"). Static addresses are needed for Internet servers that are referenced by DNS records such as Web servers, mail servers, etc. that are contacted using a domain name.
	// Ah!  My modem (from comcast) has a static MAC!  That's the "name" of my network!!!
	return String("ERR");
}
#endif
